﻿#include <xy/topo/trimesh.h>

namespace xy
{

namespace topo
{

vertex_t *trimesh::opposite_vertex(coedge_t *co) const
{
    if (co == nullptr)
        return nullptr;

    vertex_t *v = nullptr;
    if (co->next != nullptr)
        v = shape_t::end_vertex(co->next);
    return v;
}

coedge_t *trimesh::opposite_coedge_t(face_t *f, vertex_t *v) const
{
    if (f == nullptr || v == nullptr)
        return nullptr;

    // 取第一个 loop 上的所有顶点
    auto loop = f->wires.front();
    auto co = loop->coedge;

    if (shape_t::start_vertex(co) == v)
        return co->next;

    while (co->next != loop->coedge)
    {
        if (shape_t::end_vertex(co) == v)
            return co->prev;
        co = co->next;
    }
    return co;
}

bool trimesh::flip_edge(edge_t *e)
{
    if (e == nullptr)
        return false;

    // 如果是边界就不翻转
    if (e->coedge->is_boundary() || e->coedge->twin->is_boundary())
        return false;

    // 否则执行翻转
    auto co1 = e->coedge;
    auto co2 = co1->twin;

    // 获得相对的顶点
    auto v0 = shape_t::start_vertex(co1);
    auto v1 = shape_t::end_vertex(co1);
    auto v2 = opposite_vertex(co1);
    auto v3 = opposite_vertex(co2);

    // 保存构造新面需要的 coedge_t
    std::vector<coedge_t *> f1{co2->prev, co1->next};
    std::vector<coedge_t *> f2{co1->prev, co2->next};

    // 移除边
    remove(e);

    if (v2->edges.empty())
        return true;
    if (v3->edges.empty())
        return true;

    // 构造新的边和面
    auto co = create_edge(v2, v3);
    f1.push_back(co);
    f2.push_back(co->twin);
    create_face(f1[0], f1[1], f1[2]);
    create_face(f2[0], f2[1], f2[2]);

    return true;
}

} // namespace topo

} // namespace xy